﻿using CoreDomain.BusinessCore;
using DomainService.IService;
using DomainService.IService.Sys;
using Infrastructure;
using Infrastructure.IRepository.Sys;
using Model.BusinessModel;
using Model.BusinessModel.MatchFormula;
using Model.BusinessModel.OutPut.sys;
using Model.DomainModel.Sys;
using Newtonsoft.Json.Linq;
using System.Text.Json;
using Utility;
using Utility.Enum;

namespace DomainService.Service.Sys
{
    /// <summary>
    /// 菜单数据列服务接口实现
    /// </summary>
    public class SysMenuTableColsService : ISysMenuTableColsService
    {
        #region 构造实例化

        //仓储接口
        private readonly ISysMenuTableColsRepository _sysMenuTableColsRepository;

        /// <summary>
        /// 菜单仓储接口
        /// </summary>
        private readonly ISysMenuRepository _menuRepository;

        /// <summary>
        /// 基础服务
        /// </summary>
        private readonly IBaseService _baseService;

        /// <summary>
        /// 用户角色关系仓储
        /// </summary>
        private readonly ISysUserRoleRelationRepository _sysUserRoleRelationRepository;
        /// <summary>
        /// 用户底层仓储
        /// </summary>
        private readonly ISysUserRepository _sysUserRepository;

        /// <summary>
        /// 构造函数 实现依赖注入
        /// </summary>
        public SysMenuTableColsService(ISysMenuTableColsRepository sysMenuTableColsRepository, ISysMenuRepository menuRepository, IBaseService baseService, ISysUserRoleRelationRepository sysUserRoleRelationRepository, ISysUserRepository sysUserRepository)
        {
            _sysMenuTableColsRepository = sysMenuTableColsRepository;
            _menuRepository = menuRepository;
            _baseService = baseService;
            _sysUserRoleRelationRepository = sysUserRoleRelationRepository;
            _sysUserRepository = sysUserRepository;
        }

        #endregion

        #region 服务实现

        /// <summary>
        /// 反射同步数据列
        /// </summary>
        public ReceiveStatus ReflexSynchronousCols(string corporationKey, string systemKey)
        {
            return DataColsCore.SynchronousCols(corporationKey, systemKey);
        }


        /// <summary>
        /// 根据菜单id获取列
        /// </summary>
        /// <param name="menuId">菜单ID</param>
        /// <returns></returns>
        public ReceiveStatus<SysMenuTableColsOutPut> GetTableColsByMenuId(string menuId)
        {
            ReceiveStatus<SysMenuTableColsOutPut> receiveStatus = new();
            if (string.IsNullOrWhiteSpace(menuId))
                return ExceptionHelper<SysMenuTableColsOutPut>.CustomExceptionData("获取数据列时，请传入菜单key");
            var menuModel = _menuRepository.GetByKey(menuId, BaseSqlRepository.sysMenu_selectByKeySql);
            if (menuModel == null)
                return ExceptionHelper<SysMenuTableColsOutPut>.CustomExceptionData("当前菜单不存在");

            //获取菜单所有能显示的数据列
            var colsList = _sysMenuTableColsRepository.GetTableColsByMenuId(menuId);

            //匹配有规则的数据列是否显示
            List<SysMenuTableColsOutPut> list = new();
            var loginUserId = _baseService.GetUserInfo().UserId;
            //用户信息
            var sysUserModel = _sysUserRepository.GetByKey(loginUserId, BaseSqlRepository.sysUser_selectByKeySql);
            //用户角色关系
            var sysUserRoleRelationOutPutList = _sysUserRoleRelationRepository.GetSysUserRoleRelationsByUserId(loginUserId);

            foreach (var col in colsList)
            {
                if (!string.IsNullOrWhiteSpace(col.RuleJson))
                {
                    var matchFormulaList = JsonSerializer.Deserialize<List<MatchingDataInput>>(col.RuleJson);
                    var isTrue = DataAuthCore.GetDataColsAuth(matchFormulaList, sysUserModel, sysUserRoleRelationOutPutList);
                    if (isTrue)
                        list.Add(col);
                }
                else
                    list.Add(col);
            }
            receiveStatus.data = list;
            return receiveStatus;
        }


        /// <summary>
        ///  根据条件获取数据列
        /// </summary>
        /// <param name="pageResultModel">分页模型</param>
        /// <returns></returns>
        public PageResultModel<SysMenuTableColsOutPut> GetTableColsByWhere(PageResultModel pageResultModel)
        {
            var selectWhere = " and sd.IsDisplay = 1";
            JObject jobj = JObject.Parse(pageResultModel.filterJson ?? "");
            var menuId = jobj["MenuId"].ToString();
            var corporationKey = jobj["CorporationKey"].ToString();
            var systemKey = jobj["SystemKey"].ToString();
            //var ruleType = Convert.ToInt32(jobj["RuleType"]);

            if (!string.IsNullOrWhiteSpace(menuId))
            {
                var menuModel = _menuRepository.GetByKey(menuId, BaseSqlRepository.sysMenu_selectByKeySql);
                var menuIdList = MenuCore.GetChildrenRoleById(menuId, menuModel.CorporationKey ?? string.Empty, menuModel.SystemKey ?? string.Empty);
                selectWhere += string.Format("and  m.Id in ('{0}')  ", string.Join("','", menuIdList.ToArray()));
            }
            if (!string.IsNullOrWhiteSpace(corporationKey))
                selectWhere += string.Format(" and sd.CorporationKey = '{0}' ", corporationKey);
            if (!string.IsNullOrWhiteSpace(systemKey))
                selectWhere += string.Format(" and sd.SystemKey = '{0}' ", systemKey);
            //if (ruleType != 0)
            //    selectWhere += string.Format(" and sd.RuleType = '{0}' ", ruleType);

            var result = _baseService.GetAuthWhere(RuleTypeEnum.DataRowRule, "sd");
            string? authWhere = string.Empty;
            if (result.success) { authWhere = result.data[0]; }
            else
                ExceptionHelper.ThrowBusinessException(result.msg);

            pageResultModel.selectWhere = selectWhere + authWhere;

            pageResultModel.tableField = @"m.Name as MenuName,sd.FieldId,sd.MenuId,sd.RuleId,m.CorporationKey,ss.SystemName,sc.CorporationName,ss.SystemKey,su.UserName,sd.FieldCnName,
                                            FieldEnName,sd.CreateTime,sd.CreateUser,sr.AnalysisRule,sr.AnalysisRule_CN,sr.IsOpen,sr.Remark,sr.RuleJson,sr.RuleName,sr.RuleType";
            pageResultModel.tableName = @" Sys_MenuTableCols as sd 
                                            inner join Sys_Corporation as sc on sc.CorporationKey = sd.CorporationKey
                                            inner join Sys_System as ss on sd.SystemKey = ss.SystemKey
                                            inner join  Sys_Menu as m  on sd.MenuId = m.Id
                                            left join Sys_DataRule as sr on sr.RuleId = sd.RuleId
                                            inner  join Sys_User as su on su.UserId = sd.CreateUser   ";
            pageResultModel.orderByField = " sd.CreateTime ";
            pageResultModel.sortType = " desc ";
            var list = _sysMenuTableColsRepository.GetPageList<SysMenuTableColsOutPut>(pageResultModel);

            return list;
        }

        /// <summary>
        /// 根据菜单id和字段名称获取数据列
        /// </summary>
        /// <param name="menuId">菜单id</param>
        /// <param name="fieldEnName">字段名称</param>
        /// <returns>返回数据列</returns>
        public ReceiveStatus<SysMenuTableCols> GetTableColsByMenuIdOrFieldName(string menuId, string fieldEnName)
        {
            ReceiveStatus<SysMenuTableCols> receiveStatus = new();
            var colsModel = _sysMenuTableColsRepository.GetTableColsByMenuIdOrFieldName(menuId, fieldEnName);
            receiveStatus.data = colsModel == null ? null : [colsModel];
            return receiveStatus;
        }

        /// <summary>
        /// 修改字段信息
        /// </summary>
        /// <param name="sysMenuTableCols"></param>
        public ReceiveStatus UpdateTableCols(SysMenuTableCols sysMenuTableCols)
        {
            ReceiveStatus receiveStatus = new();
            _sysMenuTableColsRepository.UpdateTableCols(sysMenuTableCols);
            return receiveStatus;
        }

        /// <summary>
        /// 新增数据列
        /// </summary>
        /// <param name="sysMenuTableCols"></param>
        public ReceiveStatus InsertCols(SysMenuTableCols sysMenuTableCols)
        {
            ReceiveStatus receiveStatus = new();
            _sysMenuTableColsRepository.Insert(sysMenuTableCols, BaseSqlRepository.sysMenuTableCols_insertSql);
            return receiveStatus;
        }
        #endregion
    }
}
